package com.file.parser.socialsecurity;

import com.file.bo.ResponseData;
import com.file.bo.socialsecurity.ShanxiIndividualRecordSheet;
import com.file.bo.socialsecurity.ShanxiInsuranceParticipation;
import com.file.constant.ErrorCode;
import com.file.parser.BasePdfParser;
import com.file.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import technology.tabula.*;
import technology.tabula.detectors.SpreadsheetDetectionAlgorithm;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class ShanxiSocialSecurityPdfParser extends BasePdfParser {

    public ResponseData<String> parseShanxiSocialSecurityPdfToJson(String daId, String filePath) {
        log.info("parseShanxiSocialSecurityPdfToJson started, daId:{}", daId);
        String json = null;

        try {
            if (filePath.contains("cbzm")) {
                ShanxiInsuranceParticipation shanxiInsuranceParticipation = parseShanxiInsuranceParticipation(filePath);
                json = JsonUtils.convertObjectToJson(shanxiInsuranceParticipation);
            } else if (filePath.contains("qyd")) {//NOSONAR
                ShanxiIndividualRecordSheet shanxiIndividualRecordSheet = parseShanxiIndividualRecordSheet(filePath);
                json = JsonUtils.convertObjectToJson(shanxiIndividualRecordSheet);//NOSONAR
            } else {
                log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseShanxiSocialSecurityPdfToJson failed, new type not supported");
                return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
            }
        } catch (Exception e) {
            log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseShanxiSocialSecurityPdfToJson failed", e);
            return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
        }

        log.info("parseShanxiSocialSecurityPdfToJson completed, daId:{}", daId);
        return new ResponseData<>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
    }

    private ShanxiInsuranceParticipation parseShanxiInsuranceParticipation(String filePath) {
        ShanxiInsuranceParticipation shanxiInsuranceParticipation = new ShanxiInsuranceParticipation();
        List<ShanxiInsuranceParticipation.PaymentDetails> paymentDetailsList = new ArrayList<>();
        shanxiInsuranceParticipation.setPaymentDetailsList(paymentDetailsList);


        String pdfText = parsePdfHeaderText(filePath).replace(System.getProperty("line.separator", "\n"), StringUtils.EMPTY);
//        System.out.println(pdfText);

        String verifyNo = pdfText.substring(pdfText.indexOf("验证编号:") + 5, pdfText.indexOf("陕西省城镇职工基本养老保险")).trim();
        shanxiInsuranceParticipation.setVerifyNo(verifyNo);
        String name = pdfText.substring(pdfText.lastIndexOf("姓名:") + 3, pdfText.lastIndexOf("身份证号:")).trim();
        shanxiInsuranceParticipation.setName(name);
        String idNo = pdfText.substring(pdfText.lastIndexOf("身份证号:") + 5, pdfText.lastIndexOf("人员参保关系ID:")).trim();
        shanxiInsuranceParticipation.setIdNo(idNo);
        String personnelInsuranceRelationshipId = pdfText.substring(pdfText.lastIndexOf(" 人员参保关系ID:") + 9, pdfText.lastIndexOf("个人编号:")).trim();
        shanxiInsuranceParticipation.setPersonnelInsuranceRelationshipId(personnelInsuranceRelationshipId);
        String personalId = pdfText.substring(pdfText.lastIndexOf("个人编号:") + 5, pdfText.lastIndexOf("现缴费单位名称:")).trim();
        shanxiInsuranceParticipation.setPersonalId(personalId);
        String currentPaymentUnitName = pdfText.substring(pdfText.lastIndexOf("现缴费单位名称:") + 8, pdfText.lastIndexOf("序号")).trim();
        shanxiInsuranceParticipation.setCurrentPaymentUnitName(currentPaymentUnitName);
        String currentInsuranceAgency = pdfText.substring(pdfText.lastIndexOf("现参保经办机构:") + 8, pdfText.lastIndexOf("打印时间:")).trim();
        shanxiInsuranceParticipation.setCurrentInsuranceAgency(currentInsuranceAgency);
        String description = pdfText.substring(pdfText.lastIndexOf("说明：") + 3).trim();
        shanxiInsuranceParticipation.setDescription(description);
        String printTime = pdfText.substring(pdfText.lastIndexOf("打印时间:") + 5, pdfText.lastIndexOf("第1页")).trim();
        shanxiInsuranceParticipation.setPrintTime(printTime);

        List<List<String>> rowList = parseFileToRowList(filePath);
        for (List<String> cellList : rowList) {
            if (StringUtils.equals(cellList.get(0), "序号")) {
                continue;
            }
            ShanxiInsuranceParticipation.PaymentDetails paymentDetails = new ShanxiInsuranceParticipation.PaymentDetails();
            paymentDetails.setSerialNumber(cellList.get(0));
            paymentDetails.setPaymentYear(cellList.get(1));
            paymentDetails.setPaymentMonth(cellList.get(2));
            paymentDetails.setPersonalPayment(cellList.get(3));
            paymentDetails.setCorrespondingPaymentUnitName(cellList.get(4));
            paymentDetails.setHandlingAgency(cellList.get(5));
            paymentDetailsList.add(paymentDetails);
        }

        return shanxiInsuranceParticipation;
    }

    private ShanxiIndividualRecordSheet parseShanxiIndividualRecordSheet(String filePath) { //NOSONAR
        ShanxiIndividualRecordSheet shanxiIndividualRecordSheet = new ShanxiIndividualRecordSheet();

        String pdfText = getPdfTextByStripper(filePath).replace(System.getProperty("line.separator", "\n"), StringUtils.EMPTY);
        String recordPeriod = "";
        Matcher matcher = Pattern.compile("(\\d{4}\\s*年\\s*\\d{1,2}\\s*月\\s*至\\s*\\d{4}\\s*年\\s*\\d{1,2}\\s*月)").matcher(pdfText);
        if (matcher.find()) {
            recordPeriod = matcher.group(1).replaceAll(" ", "");
        }
        String printTime = pdfText.substring(pdfText.lastIndexOf("打印时间：") + 5).replaceAll(" ", "");
        shanxiIndividualRecordSheet.setRecordPeriod(recordPeriod);
        shanxiIndividualRecordSheet.setPrintTime(printTime);
        List<List<String>> rowList = parseFileToRowList(filePath);
        parseListToBO(rowList, shanxiIndividualRecordSheet);
        return shanxiIndividualRecordSheet;
    }

    private void parseListToBO(List<List<String>> rowList, ShanxiIndividualRecordSheet shanxiIndividualRecordSheet) {

        String sectionName = "";

        for (int i = 0; i < rowList.size(); i++) {
            List<String> cellList = rowList.get(i);
            if (StringUtils.equals(cellList.get(1), "姓名")) {
                sectionName = "个人基本信息";
            } else if (StringUtils.equals(cellList.get(1), "首次参保日期")) {
                sectionName = "首次参保日期";
            } else if (StringUtils.equalsAny(cellList.get(1), "缴费情况", "个人月缴费基数")) {
                sectionName = "缴费情况";
                continue;
            } else if (StringUtils.equals(cellList.get(1), "本年个人补缴欠费金额")) {
                sectionName = "本年个人补缴欠费金额";
                continue;
            } else if (StringUtils.equalsAny(cellList.get(1), "个人账户情况", "险种")) {
                sectionName = "个人账户情况";
                continue;
            }

            switch (sectionName) {  //NOSONAR
                case "个人基本信息":
                    if (StringUtils.equals(cellList.get(1), "姓名")) {
                        shanxiIndividualRecordSheet.setName(cellList.get(2));
                        shanxiIndividualRecordSheet.setUnitName(cellList.get(4));
                        shanxiIndividualRecordSheet.setSocialSecurityNumber(cellList.get(6));
                    }
                    break;
                case "首次参保日期":
                    if (!StringUtils.equals(cellList.get(1), "首次参保日期")) {
                        ShanxiIndividualRecordSheet.FirstInsuranceDate firstInsuranceDate = new ShanxiIndividualRecordSheet.FirstInsuranceDate();

                        firstInsuranceDate.setPension(cellList.get(1).replaceAll(" ", ""));
                        firstInsuranceDate.setMedical(cellList.get(2).replaceAll(" ", ""));
                        firstInsuranceDate.setUnemployment(cellList.get(3).replaceAll(" ", ""));
                        firstInsuranceDate.setInjury(cellList.get(4).replaceAll(" ", ""));
                        firstInsuranceDate.setMaternity(cellList.get(5).replaceAll(" ", ""));
                        shanxiIndividualRecordSheet.setFirstInsuranceDate(firstInsuranceDate);
                    }
                    break;
                case "缴费情况":
                    if (!StringUtils.equals(cellList.get(1), "养老")) {
                        ShanxiIndividualRecordSheet.PaymentSituation paymentSituation = new ShanxiIndividualRecordSheet.PaymentSituation();
                        ShanxiIndividualRecordSheet.IndividualMonthlyPaymentBase individualMonthlyPaymentBase = new ShanxiIndividualRecordSheet.IndividualMonthlyPaymentBase();
                        ShanxiIndividualRecordSheet.PensionInsuranceFee pensionInsuranceFee = new ShanxiIndividualRecordSheet.PensionInsuranceFee();
                        ShanxiIndividualRecordSheet.MedicalInsuranceFee medicalInsuranceFee = new ShanxiIndividualRecordSheet.MedicalInsuranceFee();
                        ShanxiIndividualRecordSheet.UnemploymentInsuranceFee unemploymentInsuranceFee = new ShanxiIndividualRecordSheet.UnemploymentInsuranceFee();

                        paymentSituation.setIndividualMonthlyPaymentBase(individualMonthlyPaymentBase);
                        paymentSituation.setPensionInsuranceFee(pensionInsuranceFee);
                        paymentSituation.setMedicalInsuranceFee(medicalInsuranceFee);
                        paymentSituation.setUnemploymentInsuranceFee(unemploymentInsuranceFee);
                        shanxiIndividualRecordSheet.setPaymentSituation(paymentSituation);

                        individualMonthlyPaymentBase.setPension(cellList.get(1).replaceAll(" ", ""));
                        individualMonthlyPaymentBase.setMedical(cellList.get(2).replaceAll(" ", ""));
                        individualMonthlyPaymentBase.setUnemployment(cellList.get(3).replaceAll(" ", ""));
                        individualMonthlyPaymentBase.setInjury(cellList.get(4).replaceAll(" ", ""));
                        individualMonthlyPaymentBase.setMaternity(cellList.get(5).replaceAll(" ", ""));

                        pensionInsuranceFee.setUnitContribution(cellList.get(6).replaceAll(" ", ""));
                        pensionInsuranceFee.setPersonalContribution(cellList.get(7).replaceAll(" ", ""));

                        medicalInsuranceFee.setUnitContribution(cellList.get(8).replaceAll(" ", ""));
                        medicalInsuranceFee.setPersonalContribution(cellList.get(9).replaceAll(" ", ""));

                        unemploymentInsuranceFee.setUnitContribution(cellList.get(10).replaceAll(" ", ""));
                        unemploymentInsuranceFee.setPersonalContribution(cellList.get(11).replaceAll(" ", ""));

                        paymentSituation.setInjuryFee(cellList.get(12).replaceAll(" ", ""));
                        paymentSituation.setMaternityFee(cellList.get(13).replaceAll(" ", ""));
                    }
                    break;
                case "本年个人补缴欠费金额":
                    if (!StringUtils.equals(cellList.get(1), "养老")) {
                        ShanxiIndividualRecordSheet.PersonalArrearsPaymentThisYear personalArrearsPaymentThisYear = new ShanxiIndividualRecordSheet.PersonalArrearsPaymentThisYear();
                        ShanxiIndividualRecordSheet.CompensatoryPaymentYearMonths compensatoryPaymentYearMonths = new ShanxiIndividualRecordSheet.CompensatoryPaymentYearMonths();
                        ShanxiIndividualRecordSheet.ActualPaymentMonthsByYearEnd actualPaymentMonthsByYearEnd = new ShanxiIndividualRecordSheet.ActualPaymentMonthsByYearEnd();
                        ShanxiIndividualRecordSheet.CumulativeArrearsMonths cumulativeArrearsMonth = new ShanxiIndividualRecordSheet.CumulativeArrearsMonths();
                        ShanxiIndividualRecordSheet.PaymentSituation paymentSituation = shanxiIndividualRecordSheet.getPaymentSituation();
                        paymentSituation.setPersonalArrearsPaymentThisYear(personalArrearsPaymentThisYear);
                        paymentSituation.setCompensatoryPaymentYearMonths(compensatoryPaymentYearMonths);
                        paymentSituation.setActualPaymentMonthsByYearEnd(actualPaymentMonthsByYearEnd);
                        paymentSituation.setCumulativeArrearsMonths(cumulativeArrearsMonth);

                        personalArrearsPaymentThisYear.setPension(cellList.get(1).replaceAll(" ", ""));
                        personalArrearsPaymentThisYear.setMedical(cellList.get(2).replaceAll(" ", ""));
                        personalArrearsPaymentThisYear.setUnemployment(cellList.get(3).replaceAll(" ", ""));

                        compensatoryPaymentYearMonths.setPension(cellList.get(4).replaceAll(" ", ""));
                        compensatoryPaymentYearMonths.setMedical(cellList.get(5).replaceAll(" ", ""));
                        compensatoryPaymentYearMonths.setUnemployment(cellList.get(6).replaceAll(" ", ""));

                        actualPaymentMonthsByYearEnd.setPension(cellList.get(7).replaceAll(" ", ""));
                        actualPaymentMonthsByYearEnd.setMedical(cellList.get(8).replaceAll(" ", ""));
                        actualPaymentMonthsByYearEnd.setUnemployment(cellList.get(9).replaceAll(" ", ""));

                        cumulativeArrearsMonth.setPension(cellList.get(10).replaceAll(" ", ""));
                        cumulativeArrearsMonth.setMedical(cellList.get(11).replaceAll(" ", ""));
                        cumulativeArrearsMonth.setUnemployment(cellList.get(12).replaceAll(" ", ""));
                    }
                    break;

                case "个人账户情况":
                    ShanxiIndividualRecordSheet.PersonalAccount personalAccount = new ShanxiIndividualRecordSheet.PersonalAccount();
                    shanxiIndividualRecordSheet.setPersonalAccount(personalAccount);
                    personalAccount.setInsuranceType(cellList.get(1).replaceAll(" ", ""));
                    personalAccount.setAccumulatedSavings(cellList.get(2).replaceAll(" ", ""));
                    personalAccount.setAnnualBookkeepingAmount(cellList.get(3).replaceAll(" ", ""));
                    personalAccount.setAnnualPersonalExpenditure(cellList.get(4).replaceAll(" ", ""));
                    personalAccount.setAnnualInterest(cellList.get(5).replaceAll(" ", ""));
                    personalAccount.setYearEndAccumulatedSavings(cellList.get(6).replaceAll(" ", ""));
                    return;
            }
        }
    }

    private List<List<String>> parseFileToRowList(String filePath) {
        // 1. 读取文件
        File pdf = new File(filePath);

        //页面所有table的记录，每一个元素代表下面一条记录cellList
        List<List<String>> rowList = new ArrayList<>();

        // 2. pdfbox读取PDDocument
        try (PDDocument pdfDocument = PDDocument.load(pdf)) {
            // 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
            ObjectExtractor objectExtractor = new ObjectExtractor(pdfDocument);
            SpreadsheetDetectionAlgorithm detectionAlgorithm = new SpreadsheetDetectionAlgorithm();
            Map<Integer, List<Rectangle>> pageNumber2RectangleListMap = new HashMap<>();//key为页的序号， value为对应的Rectangle的list

            // 4. 获取每页的PageIterator
            PageIterator pageIterator = objectExtractor.extract();

            // 5. 解析每页的Rectangle
            // 如果单页pdf中有多个Rectangle，则解析出来的List<Rectangle>会有多个对象
            while (pageIterator.hasNext()) {
                Page page = pageIterator.next();
                List<Rectangle> rectangleList = detectionAlgorithm.detect(page);
                if (rectangleList.size() > 0) {
                    pageNumber2RectangleListMap.put(page.getPageNumber(), rectangleList);
                }
            }

            // 6.通过table位置获取表格具体内容
            SpreadsheetExtractionAlgorithm extractionAlgorithm = new SpreadsheetExtractionAlgorithm();

            // 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
            for (Map.Entry<Integer, List<Rectangle>> entry : pageNumber2RectangleListMap.entrySet()) {
                Page page = objectExtractor.extract(entry.getKey());
                // 默认每页只有一个表格，因此获取第0个rectangle
                Rectangle rectangle = entry.getValue().get(0);
                Page area = page.getArea(rectangle.getTop(), rectangle.getLeft(), rectangle.getBottom(), rectangle.getRight());

                // 如果每页有多个表格，解析每一个table
                List<Table> tableList = extractionAlgorithm.extract(area);
                for (Table table : tableList) {
                    for (int i = 0; i < table.getRowCount(); i++) {
                        List<String> cellList = new ArrayList<>();//一条记录，每个单元格占一个元素
                        for (int j = 0; j < table.getColCount(); j++) {
                            cellList.add(table.getCell(i, j).getText(false));
                        }
                        rowList.add(cellList);
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return rowList;
    }

    public static void main(String[] args) {
        ShanxiSocialSecurityPdfParser shanxiSocialSecurityPdfParser = new ShanxiSocialSecurityPdfParser();
        String filePath, json;
        // 参保证明
//         filePath = "D:\\data\\file\\socialsecurity\\陕西\\app-gjzwfw-dzsb_cbzm.pdf";
//         json = shanxiSocialSecurityPdfParser.parseShanxiSocialSecurityPdfToJson("", filePath).getData();
//        System.out.println(json);
//
//      // 权益单
        filePath = "D:\\data\\file\\socialsecurity\\陕西\\zd4akdkf1742834396153864192_app-gjzwfw-dzsb_origins\\app-gjzwfw-dzsb_qyd.pdf";
        json = shanxiSocialSecurityPdfParser.parseShanxiSocialSecurityPdfToJson("", filePath).getData();
        System.out.println(json);
//
//        filePath = "D:\\data\\file\\socialsecurity\\陕西\\zd47iaqw1746562653294899200_app-gjzwfw-dzsb_origins\\app-gjzwfw-dzsb_qyd.pdf";
//        json = shanxiSocialSecurityPdfParser.parseShanxiSocialSecurityPdfToJson("", filePath).getData();
//        System.out.println(json);

    }


}
